/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.rh.game.impl;

import com.rh.game.ChatWithConditions;
import com.rh.game.Character;
import com.rh.game.Chapter;
import com.rh.game.GameCondition;
import com.rh.game.GameEffect;
import com.rh.game.GameObject;
import com.rh.game.Tile;

import com.rh.game.chat.ChatImage;
import com.rh.game.chat.ChatResponse;

import com.rh.game.loader.ChatKeys;
import com.rh.game.loader.GameConditionKeys;
import com.rh.game.loader.GameEffectKeys;
import com.rh.game.loader.Loader;
import com.rh.game.loader.Portal;
import com.rh.game.loader.MapBuffer;
import com.rh.game.loader.MapKeys;
import com.rh.game.loader.WorldBuffer;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 *
 * @author Hayden
 */
public class DemoGame {
    private static void debug(Object o)  {
        System.out.println("DemoGame: " + o);
    }
    
    private static World1 createWorld(Character player, List<Character> npcs, List<GameObject1> pObjects, List<Chapter> chapters, Collection<MapGrid> pMapGrids, List<Tile> pTiles)  {
        List<GameObject> objects = new ArrayList<GameObject>(pObjects);
        return new World1(player, npcs, objects, chapters, pMapGrids, pTiles);
    }

    private static Character whoIs(String pSpeakerID, Character player, HashMap<String, Character> npcMap)  {
        Character speaker = null;
        speaker = npcMap.get(pSpeakerID);
        if (speaker == null)  {
            if (player.getID().equals(pSpeakerID))  speaker = player;
        }
        if (speaker == null)  {
            if ("NARRATOR".equals(pSpeakerID))  {
                speaker = Character.NARRATOR;
            }
        }
        if (speaker == null)  {
            debug("Who is: " + pSpeakerID);
            speaker = Character.NULL;
        }
        
        return speaker;
    }
    
    private static List<GameCondition> createConditions(final ChatKeys ck, Character player, HashMap<String, Character> npcMap)  {
        List<GameCondition> cs = new ArrayList<GameCondition>();
        
        for (GameConditionKeys gck : ck.getConditions())  {
            Character c = whoIs(gck.getWhomID(), player, npcMap);
            cs.add(new GameCondition1(gck.getType(), c));
        }
        
        return cs;
    }

    private static List<GameEffect> createEffects(final ChatKeys ck, Character player, HashMap<String, Character> npcMap, HashMap<String, GameObject1> objects)  {
        List<GameEffect> e = new ArrayList<GameEffect>();

        for (GameEffectKeys gek : ck.getGameEffectKeys())  {
            Character c1 = whoIs(gek.getWhomID(), player, npcMap);
            Character c2 = whoIs(gek.getWhomID2(), player, npcMap);
            
            GameObject go = objects.get(gek.getObjectID());
            if (go == null)  go = GameObject.NULL;
            
            GameEffect1 ge1 = new GameEffect1(
                gek.getType(), 
                go, 
                c1, 
                gek.getLocation(), 
                c2
            );
            e.add(ge1);
        }
        
        if (e.size() > 0)  System.out.println(e);
        return e;
    }
    
    private static List<Chapter> createChapters2(final WorldBuffer wb, Character player, HashMap<String, Character> npcMap, HashMap<String, GameObject1> objects)  {
        List<ChatWithConditions> chat1 = new ArrayList<ChatWithConditions>();
        
        for (ChatKeys ck : wb.getConversationBuffer().getChats())  {
            Character speaker = whoIs(ck.getSpeakerID(), player, npcMap);
            
            ArrayList<ChatResponse> resp = new ArrayList<ChatResponse>(ck.getResponses());
            List<GameCondition> pre = createConditions(ck, player, npcMap);
    
            List<GameEffect> effects = createEffects(ck, player, npcMap, objects);
            
            ChatWithConditions cwc = new ChatWithConditions(
                ck.getID(), 
                ck.getText(), 
                ck.isIntro(), 
                speaker, // zagros, 
                effects, 
                null, // mp3 file???
                ChatImage.NULL, 
                resp, 
                pre // aliceConditions1
            );
            
            chat1.add(cwc);
        }
        
        List<Chapter> chapters = new ArrayList<Chapter>();
        chapters.add(new Chapter1("Chapter1", chat1));
        return chapters;
    }

    private static void initializeWorld(World1 world, List<GameEffectKeys> init)  {
        for (GameEffectKeys gek : init)  {
            Character whom = world.getCharacter(gek.getWhomID());            
            GameObject go = world.getGameObject(gek.getObjectID());
            GameEffect1 ge = new GameEffect1(gek.getType(), go, whom, gek.getLocation());
            world.gameEffect(ge);
        }
    }
    
    public static void main(String[] args)  {
        try  {
            getGameWorld();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static World1 getGameWorldFromFile(String pFile) throws Exception {        
        File f = new File(pFile);
        if (!f.exists())  {
            System.out.println("File " + pFile + " does not exist");
        }
        InputStream is = null;
        World1 w = null;
        
        try  {
            is = new FileInputStream(f);
            w = getGameWorld(is);
        }
        finally {
            Loader.close(is);
        }
        
        return w;
    }

    static Collection<MapGrid> createMapGrids(MapBuffer mapBuffer, List<Tile> pTiles)  {
        debug(pTiles);
        Map<String, Tile> gridMap = new TreeMap<String, Tile>();
        for (Tile t : pTiles)  {
            gridMap.put(t.getGridString(), t);
        }

        Collection<MapGrid> grids = new ArrayList<MapGrid>();
        for (MapKeys mk : mapBuffer.getMapKeys())  {
            debug(mk);
            grids.add(
                new MapGrid(
                    mk.getZoneID(), 
                    mk.getRows(), 
                    gridMap, 
                    mk.getPortals()
                )
            );
        }
        
        return grids;
    }
    
    static World1 createWorld(final WorldBuffer wb)  {
        List<Tile> tiles = null;
        List<Character> npcs = null;
        HashMap<String, GameObject1> objects = new HashMap<String, GameObject1>();

        tiles = new ArrayList<Tile>(wb.getTiles());
        for (GameObject1 go : wb.getObjects())  {
            objects.put(go.getID(), go);
        }

        Character player = Character.NULL;
        for (Character c : wb.getPlayer())  {
            player = c;
        }
        debug("Player is: " + player.getID() + ", " + player.getName());
        
        npcs = wb.getNpcs();
        HashMap<String, Character> npcMap = new HashMap<String, Character>();
        for (Character c : npcs)  {
            npcMap.put(c.getID(), c);
        }
        
        List<Chapter> chapters = createChapters2(wb, player, npcMap, objects);

        World1 w = createWorld(
            player, 
            npcs, 
            wb.getObjects(), 
            chapters, 
            createMapGrids(wb.getMapBuffer(), tiles), 
            tiles
        );
        
        initializeWorld(w, wb.getInitialization().getInitializations());
        return w;
    }
    
    private static World1 getGameWorld(final InputStream is) throws Exception {        
        return createWorld(Loader.load(is));
    }
    
    public static World1 getGameWorld() throws Exception {        
        Loader l = new Loader();
        WorldBuffer wb = l.load("/resources/games/game1.xml");
        return createWorld(wb);
    }
}
